package yanyan.com.tochar;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

import com.gs.buluo.common.widget.LoadingDialog;
import com.luck.picture.lib.PictureSelector;
import com.luck.picture.lib.entity.LocalMedia;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import yanyan.com.tochar.adpter.FullyGridLayoutManager;
import yanyan.com.tochar.adpter.GridImageAdapter;
import yanyan.com.tochar.utils.CoreUtil;
import yanyan.com.tochar.utils.PictureSelectUtil;
import yanyan.com.tochar.utils.ToastUtil;

/**
 * 素描图片制作
 */
public class FunsSketchActivity extends Activity {
    private RecyclerView recyclerView;
    private GridImageAdapter adapter;
    private ImageView imgRes;
    private Bitmap newBitmap;
    private List imgList= new ArrayList<>();//图片集合
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_funs_sketch);

        recyclerView=findViewById(R.id.sketch_recycler);
        imgRes = findViewById(R.id.sketch_res_img);


        //初始化图片选择
        FullyGridLayoutManager manager = new FullyGridLayoutManager(this, 4, GridLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(manager);
        adapter = new GridImageAdapter(this, new GridImageAdapter.onAddPicClickListener() {
            @Override
            public void onAddPicClick() {
                PictureSelectUtil.selectPohto(FunsSketchActivity.this,3306);
            }
        });
        adapter.setList(imgList);
        adapter.setSelectMax(1);
        recyclerView.setAdapter(adapter);

        //统计各功能
        CoreUtil.statisticalFuns(this,"funs_sketch_img");
    }


    /**
     * 选择图片事件
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==RESULT_OK){
            imgList = PictureSelector.obtainMultipleResult(data);
            adapter.setList(imgList);
            adapter.notifyDataSetChanged();
        }
    }


    public void createSketchImg(View view){
        if(imgList!=null && imgList.size()>0){
            LoadingDialog.getInstance().show(FunsSketchActivity.this, "正在制作中...", false);//加载
            Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> e) throws Exception {
                    try{
                        LocalMedia localMedia= (LocalMedia) imgList.get(0);
                        String path="";
                        if(CoreUtil.isAndroidQ()){
                            path=localMedia.getAndroidQToPath();
                        }else {
                            path= localMedia.getPath();
                        }
                        Bitmap bitmap = PictureSelectUtil.getBitmap(path);
                        int p=bitmap.getWidth()/2000;
                        if(p>1){
                            bitmap=PictureSelectUtil.getCompressPhoto(path,p);
                        }
                        Bitmap sketch = createSketch(bitmap);
                        newBitmap=sketch;


                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                imgRes.setImageBitmap(newBitmap);
                            }
                        });
                        e.onComplete();
                    }catch (Exception e1){
                        e.onError(e1);
                    }
                }
            }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
                }
                @Override
                public void onNext(String s) {

                }
                @Override
                public void onError(Throwable e) {
                    LoadingDialog.getInstance().dismissDialog();
                    ToastUtil.showShotToast(FunsSketchActivity.this, "生成失败");
                }
                @Override
                public void onComplete() {
                    LoadingDialog.getInstance().dismissDialog();
                    ToastUtil.showShotToast(FunsSketchActivity.this, "生成成功");
                }
            });
        }else {
            ToastUtil.showLongToast(this,"请选择图片");
        }
    }

    public void savenSketchImg(View view){
        if(newBitmap!=null){
            String path = PictureSelectUtil.savePhotoToSD(newBitmap, this);
            ToastUtil.showLongToast(this,"图片保存成功"+path);
        }

    }


    private Bitmap createSketch(Bitmap bitmap){
//        Bitmap bitmap1 = testGaussBlur(bitmap,100,1);
        Bitmap pencli = createPencli(bitmap);
        return pencli;

    }

    /**
     * 去色
     * @param pixels
     * @param width
     * @param height
     * @return
     */
   private int[] getGray(int[] pixels, int width, int height)
    {
        int gray[] = new int[width * height];
        for (int i = 0; i < width - 1; i++)
        {
            for (int j = 0; j < height - 1; j++)
            {
                int index = width * j + i;
                int rgba = pixels[index];
                int g = ((rgba & 0x00FF0000) >> 16) * 3 + ((rgba & 0x0000FF00) >> 8) * 6 + ((rgba & 0x000000FF)) * 1;
                gray[index] = g / 10;
            }
        }
        return gray;
    }

    /**
     * 对去色灰度图取反色
     * @param gray
     * @return
     */
    public int[] getInverse(int[] gray)
    {
        int[] inverse = new int[gray.length];

        for (int i = 0, size = gray.length; i < size; i++)
        {
            inverse[i] = 255 - gray[i];
        }
        return inverse;
    }

    /**
     * 对反色高斯模糊
     * @param inverse
     * @param width
     * @param height
     * @return
     */
    public int[] guassBlur(int[] inverse, int width, int height)
    {
        int[] guassBlur = new int[inverse.length];

        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                int temp = width * (j) + (i);
                if ((i == 0) || (i == width - 1) || (j == 0) || (j == height - 1))
                {
                    guassBlur[temp] = 0;
                }
                else
                {
                    int i0 = width * (j - 1) + (i - 1);
                    int i1 = width * (j - 1) + (i);
                    int i2 = width * (j - 1) + (i + 1);
                    int i3 = width * (j) + (i - 1);
                    int i4 = width * (j) + (i);
                    int i5 = width * (j) + (i + 1);
                    int i6 = width * (j + 1) + (i - 1);
                    int i7 = width * (j + 1) + (i);
                    int i8 = width * (j + 1) + (i + 1);

                    int sum = inverse[i0] + 2 * inverse[i1] + inverse[i2] + 2 * inverse[i3] + 4 * inverse[i4] + 2 * inverse[i5] + inverse[i6] + 2 * inverse[i7] + inverse[i8];

                    sum /= 16;

                    guassBlur[temp] = sum;
                }
            }
        }
        return guassBlur;
    }

    /**
     * 对取得高斯灰度值与 去色灰度值 进行颜色减淡混合
     * @param guassBlur
     * @param gray
     * @param width
     * @param height
     * @return
     */
    public int[] deceasecolorCompound(int[] guassBlur, int[] gray, int width, int height)
    {
        int a, b, temp;
        float ex;
        int[] output = new int[guassBlur.length];

        for(int i=0 ; i< width ; i++)
        {
            for(int j=0 ; j<height ; j++)
            {
                int index = j*width + i;
                b = guassBlur[index];
                a = gray[index];

                temp = a+a*b/(256-b);
                ex = temp*temp*1.0f/255/255;
                temp = (int) (temp *ex);

                a = Math.min(temp, 255);

                output[index] = a;
            }
        }
        return output;
    }

    /**
     * 根据混合结果灰度值生成图片
     * @param pixels
     * @param output
     * @param width
     * @param height
     * @return
     */
    public Bitmap create(int[] pixels , int[] output,int width , int height)
    {
        for(int i=0 ,size = pixels.length ; i<size ; i++)
        {
            int gray = output[i];
            int pixel = (pixels[i] & 0xff000000) | (gray<<16) | (gray<< 8) | gray;//注意加上原图的 alpha通道

            output[i] = pixel;
        }

        return Bitmap.createBitmap(output, width, height, Bitmap.Config.RGB_565);
    }


    public Bitmap createPencli(Bitmap bitmap)
    {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

        int[] gray = getGray(pixels, width, height);
        int[] inverse = getInverse(gray);

        int[] guassBlur = guassBlur(inverse, width, height);

        int[] output = deceasecolorCompound(guassBlur , gray , width , height);

        return create(pixels, output, width, height);
    }





//    /**
//     * 去色
//     * @param bitmap
//     * @return
//     */
//    public int[] discolor(Bitmap bitmap) {
//
//        int picHeight = bitmap.getHeight();
//        int picWidth = bitmap.getWidth();
//
//        int[] pixels = new int[picWidth * picHeight];
//        bitmap.getPixels(pixels, 0, picWidth, 0, 0, picWidth, picHeight);
//
//        for (int i = 0; i < picHeight; ++i) {
//            for (int j = 0; j < picWidth; ++j) {
//                int index = i * picWidth + j;
//                int color = pixels[index];
//                int r = (color & 0x00ff0000) >> 16;
//                int g = (color & 0x0000ff00) >> 8;
//                int b = (color & 0x000000ff);
//                int grey = (int) (r * 0.3 + g * 0.59 + b * 0.11);
//                pixels[index] = grey << 16 | grey << 8 | grey | 0xff000000;
//            }
//        }
//        return pixels;
//    }
//
//    /**
//     * 反向
//     * @param pixels
//     * @return
//     */
//    public int[] reverseColor(int[] pixels) {
//
//        int length = pixels.length;
//        int[] result = new int[length];
//        for (int i = 0; i < length; ++i) {
//            int color = pixels[i];
//            int r = 255 - (color & 0x00ff0000) >> 16;
//            int g = 255 - (color & 0x0000ff00) >> 8;
//            int b = 255 - (color & 0x000000ff);
//            result[i] = r << 16 | g << 8 | b | 0xff000000;
//        }
//        return result;
//    }
//
//
//    /**
//     * 高斯模糊
//     * @param data
//     * @param width
//     * @param height
//     * @param radius
//     * @param sigma
//     */
//    public void gaussBlur(int[] data, int width, int height, int radius,
//                                 float sigma) {
//
//        float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma));
//        float pb = -1.0f / (2 * sigma * sigma);
//
//        // generate the Gauss Matrix
//        float[] gaussMatrix = new float[radius * 2 + 1];
//        float gaussSum = 0f;
//        for (int i = 0, x = -radius; x <= radius; ++x, ++i) {
//            float g = (float) (pa * Math.exp(pb * x * x));
//            gaussMatrix[i] = g;
//            gaussSum += g;
//        }
//
//        for (int i = 0, length = gaussMatrix.length; i < length; ++i) {
//            gaussMatrix[i] /= gaussSum;
//        }
//
//        // x direction
//        for (int y = 0; y < height; ++y) {
//            for (int x = 0; x < width; ++x) {
//                float r = 0, g = 0, b = 0;
//                gaussSum = 0;
//                for (int j = -radius; j <= radius; ++j) {
//                    int k = x + j;
//                    if (k >= 0 && k < width) {
//                        int index = y * width + k;
//                        int color = data[index];
//                        int cr = (color & 0x00ff0000) >> 16;
//                        int cg = (color & 0x0000ff00) >> 8;
//                        int cb = (color & 0x000000ff);
//
//                        r += cr * gaussMatrix[j + radius];
//                        g += cg * gaussMatrix[j + radius];
//                        b += cb * gaussMatrix[j + radius];
//
//                        gaussSum += gaussMatrix[j + radius];
//                    }
//                }
//
//                int index = y * width + x;
//                int cr = (int) (r / gaussSum);
//                int cg = (int) (g / gaussSum);
//                int cb = (int) (b / gaussSum);
//
//                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
//            }
//        }
//
//        // y direction
//        for (int x = 0; x < width; ++x) {
//            for (int y = 0; y < height; ++y) {
//                float r = 0, g = 0, b = 0;
//                gaussSum = 0;
//                for (int j = -radius; j <= radius; ++j) {
//                    int k = y + j;
//                    if (k >= 0 && k < height) {
//                        int index = k * width + x;
//                        int color = data[index];
//                        int cr = (color & 0x00ff0000) >> 16;
//                        int cg = (color & 0x0000ff00) >> 8;
//                        int cb = (color & 0x000000ff);
//
//                        r += cr * gaussMatrix[j + radius];
//                        g += cg * gaussMatrix[j + radius];
//                        b += cb * gaussMatrix[j + radius];
//
//                        gaussSum += gaussMatrix[j + radius];
//                    }
//                }
//
//                int index = y * width + x;
//                int cr = (int) (r / gaussSum);
//                int cg = (int) (g / gaussSum);
//                int cb = (int) (b / gaussSum);
//                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
//            }
//        }
//    }
//
//
//    /**
//     * 颜色减淡
//     * @param baseColor
//     * @param mixColor
//     */
//    public  void colorDodge(int[] baseColor, int[] mixColor) {
//
//        for (int i = 0, length = baseColor.length; i < length; ++i) {
//            int bColor = baseColor[i];
//            int br = (bColor & 0x00ff0000) >> 16;
//            int bg = (bColor & 0x0000ff00) >> 8;
//            int bb = (bColor & 0x000000ff);
//
//            int mColor = mixColor[i];
//            int mr = (mColor & 0x00ff0000) >> 16;
//            int mg = (mColor & 0x0000ff00) >> 8;
//            int mb = (mColor & 0x000000ff);
//
//            int nr = colorDodgeFormular(br, mr);
//            int ng = colorDodgeFormular(bg, mg);
//            int nb = colorDodgeFormular(bb, mb);
//
//            baseColor[i] = nr << 16 | ng << 8 | nb | 0xff000000;
//        }
//
//    }
//    private static int colorDodgeFormular(int base, int mix) {
//        int a=255 - mix;
//        if(a==0){
//            a=1;
//        }
//        int result = base + (base * mix) /a;
//        result = result > 255 ? 255 : result;
//        return result;
//    }
//
//
//    public  Bitmap testGaussBlur(Bitmap src, int r, int fai) {
//
//        int width = src.getWidth();
//        int height = src.getHeight();
//
//        int[] pixels = this.discolor(src);
//        int[] copixels = this.reverseColor(pixels);
//        this.gaussBlur(copixels, width, height, r, fai);
//        this.colorDodge(pixels, copixels);
//
//        Bitmap bitmap = Bitmap.createBitmap(pixels, width, height,
//                Bitmap.Config.RGB_565);
//        return bitmap;
//  }
}
